package Modelo;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import java.awt.Image;
import java.awt.Toolkit;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

public class Pooglin{
		
	/* La posicion que se encuentra el pooglin en el 
	 * planeta */
	private Posicion posicionEnPlaneta;
	/* La habilidad o herramienta que se encuentra puesta
	 * sobre el pooglin */
	private Habilidad habilidad;
	/* La velocidad en que va el pooglin (igualmente 
	 * tambien se puede crear una nueva clase Velocidad
	 * y que describa los terminos en la misma clase
	 * pero por el momento lo dejo para el momento necesario)
	 */
	private int velocidad;
	/* El terreno en que se encuentra el pooglin */
	private Terreno terrenoActual;
	/* La cantidad de bloques que estuvo cayendo el pooglin */
	private int bloquesCaidos;
	/* La direccion actual en que va el pooglin */
	private boolean haciaDerecha;
	
	private List <Bloque> bloquesContiguos;
	
	private Bloque bloqueActual;
	
	private Image imagenPooglinDerecha;

	private Image imagenPooglinIzquierda;
	
	private Boolean estaMuerto;

	private Boolean estaSalvado;

	public Pooglin (Posicion posicion, Terreno terreno){
		this.terrenoActual = terreno;
		this.posicionEnPlaneta = posicion;
		this.setHabilidad(null);
		this.velocidad=1;
		this.bloquesCaidos=0;
		this.estaMuerto=false;
		this.estaSalvado=false;
		this.haciaDerecha=true;
		this.imagenPooglinDerecha = Toolkit.getDefaultToolkit().getImage("imagenes/pooglinDerecha.gif");
		this.imagenPooglinIzquierda = Toolkit.getDefaultToolkit().getImage("imagenes/pooglinIzquierda.gif");

	}
	
	public Pooglin (Element xmlElement){
		this.velocidad=Integer.parseInt(xmlElement.getAttribute("velocidad"));
		this.bloquesCaidos=Integer.parseInt(xmlElement.getAttribute("bloquesCaidos"));
		this.haciaDerecha=Boolean.parseBoolean(xmlElement.getAttribute("haciaDerecha"));
		this.posicionEnPlaneta=new Posicion((Element)xmlElement.getElementsByTagName("Posicion").item(0));
		this.estaMuerto=Boolean.parseBoolean(xmlElement.getAttribute("estaMuerto"));
		this.estaSalvado=Boolean.parseBoolean(xmlElement.getAttribute("estaSalvado"));
		if (Integer.parseInt(xmlElement.getAttribute("Habilidad"))==1){
			String tipoHabilidad=((Element)xmlElement.getElementsByTagName("Habilidad").item(0)).getAttribute("Tipo");
			this.habilidad=crearHabilidad(Constantes.toTipoHabilidad(tipoHabilidad));
		}else{
			this.habilidad=null;
		}
		this.imagenPooglinDerecha = Toolkit.getDefaultToolkit().getImage("imagenes/pooglinDerecha.gif");
		this.imagenPooglinIzquierda = Toolkit.getDefaultToolkit().getImage("imagenes/pooglinIzquierda.gif");
	}
	
	private Habilidad crearHabilidad(Constantes.TIPOS_DE_HABILIDAD h){
		Habilidad habilidad = null;
		switch (h){
			case CONGELAMIENTO : habilidad = new Congelamiento();
			break;
			case PLATILLOVOLADOR : habilidad = new PlatilloVolador();
			break;
			case RAYOLASER : habilidad = new RayoLaser();
			break;
			case TALADROULTRASONICO : habilidad = new TaladroUltraSonico();
			break;
			case TELETRANSPORTACION : habilidad = new Teletransportacion();
			break;
			case TUNELELECTROMAGNETICO : habilidad = new TunelElectromagnetico();
			break;
		}
		return habilidad;
	}
	
	public List<Bloque> getBloquesContiguos() {
		return bloquesContiguos;
	}

	public Posicion getPosicion(){
		return this.posicionEnPlaneta;
	}
	
	public Habilidad getHabilidad() {
		return habilidad;
	}

	public void setHabilidad(Habilidad habilidad) {
		this.habilidad = habilidad;
	}

	public Terreno getTerrenoActual() {
		return terrenoActual;
	}

	public void cambiarDireccion(){
		if (this.haciaDerecha()){
			this.haciaDerecha=false;
		}else{
			this.haciaDerecha=true;
		}
	}
	
	public boolean haciaDerecha(){
		return this.haciaDerecha==true;
	}
	
	public void reiniciarBloquesCaidos() {
		this.bloquesCaidos = 0;
	}

	public int getBloquesCaidos(){
		return this.bloquesCaidos;
	}
	
	public void caer(){
		this.posicionEnPlaneta.setPosicionY(this.posicionEnPlaneta.getPosicionY()+1);
		this.bloquesCaidos++;
		if (this.bloquesCaidos>Constantes.CAIDA_MAX)					
			this.morir();
	}
	
	public boolean seMovio(){
		boolean movio=true;
		if ((bloqueActual.getPosicion().getPosicionX()==
		this.posicionEnPlaneta.getPosicionX())&&
			(bloqueActual.getPosicion().getPosicionY()==
			this.posicionEnPlaneta.getPosicionY())){
				movio=false;
				return movio;
			}
		return movio;
			
	}
	
	public void caminar(){
		if (haciaDerecha()){
			this.posicionEnPlaneta.setPosicionX(this.posicionEnPlaneta.getPosicionX()+1);
		}else{
			this.posicionEnPlaneta.setPosicionX(this.posicionEnPlaneta.getPosicionX()-1);
		}
	}
	
	public void moverDiagonalArriba(){
		if (haciaDerecha()){
			this.posicionEnPlaneta.setPosicionX(this.posicionEnPlaneta.getPosicionX()+1);
			this.posicionEnPlaneta.setPosicionY(this.posicionEnPlaneta.getPosicionY()-1);
		}else{
			this.posicionEnPlaneta.setPosicionX(this.posicionEnPlaneta.getPosicionX()-1);
			this.posicionEnPlaneta.setPosicionY(this.posicionEnPlaneta.getPosicionY()-1);
		}
	}
	public void setVelocidadNormal() {
		this.velocidad = 1;
	}
	
	public int getVelocidad() {
		return velocidad;
	}

	// Obtiene los bloques continguos //
	public void reconocerBloquesContinguos(){
		this.bloquesContiguos=new LinkedList<Bloque>();	
		this.bloqueActual = this.terrenoActual.queBloqueHay(
				this.posicionEnPlaneta.getPosicionX(),this.posicionEnPlaneta.getPosicionY());
		
		this.bloquesContiguos.add(this.terrenoActual.queBloqueHay(
				this.posicionEnPlaneta.getPosicionX(),this.posicionEnPlaneta.getPosicionY()+1));
				
		if (this.haciaDerecha()){
			this.bloquesContiguos.add(this.terrenoActual.queBloqueHay(
			this.posicionEnPlaneta.getPosicionX()+1,this.posicionEnPlaneta.getPosicionY()));
			this.bloquesContiguos.add(this.terrenoActual.queBloqueHay(
			this.posicionEnPlaneta.getPosicionX()+1,this.posicionEnPlaneta.getPosicionY()+1));
			this.bloquesContiguos.add(this.terrenoActual.queBloqueHay(
			this.posicionEnPlaneta.getPosicionX()+1,this.posicionEnPlaneta.getPosicionY()-1));
			this.bloquesContiguos.add(this.terrenoActual.queBloqueHay(
			this.posicionEnPlaneta.getPosicionX()-1,this.posicionEnPlaneta.getPosicionY()));
			this.bloquesContiguos.add(this.terrenoActual.queBloqueHay(
			this.posicionEnPlaneta.getPosicionX()-1,this.posicionEnPlaneta.getPosicionY()+1));
		}else{
			this.bloquesContiguos.add(this.terrenoActual.queBloqueHay(
			this.posicionEnPlaneta.getPosicionX()-1,this.posicionEnPlaneta.getPosicionY()));			
			this.bloquesContiguos.add(this.terrenoActual.queBloqueHay(
			this.posicionEnPlaneta.getPosicionX()-1,this.posicionEnPlaneta.getPosicionY()-1));
			this.bloquesContiguos.add(this.terrenoActual.queBloqueHay(
			this.posicionEnPlaneta.getPosicionX()+1,this.posicionEnPlaneta.getPosicionY()));
			this.bloquesContiguos.add(this.terrenoActual.queBloqueHay(
			this.posicionEnPlaneta.getPosicionX()+1,this.posicionEnPlaneta.getPosicionY()+1));
		}
	}
	
	public synchronized void moverConHabilidad(){
		this.reconocerBloquesContinguos();
		Iterator <Bloque> iterador =this.bloquesContiguos.iterator();
		while (iterador.hasNext()){
			Bloque esteBloque=iterador.next();	
			if ((this!=null)&&(!this.seMovio())&&(this.getHabilidad()!=null)){
				esteBloque.actuarConHabilidad(this);
			}
		}
	}

	public synchronized void mover(){
		// Aca se tiene que poder mover un paso en las
		// coordenadas que corresponda, pero al encontrarse
		// con algun obstaculo, se tiene que responder
		// de acuerdo a la situacion
		if (this.getHabilidad()!=null)
			this.moverConHabilidad();
		else{		
			this.reconocerBloquesContinguos();
			Iterator <Bloque> iterador =this.bloquesContiguos.iterator();
			while (iterador.hasNext()&&(!this.seMovio())){
				Bloque esteBloque=iterador.next();	
				if ((this!=null)&&(!this.seMovio())&&(esteBloque.getPrioridad()==2)){
					esteBloque.actuar(this);
				}
			}
			iterador =this.bloquesContiguos.iterator();
			while (iterador.hasNext()&&(!this.seMovio())){
				Bloque esteBloque=iterador.next();	
				if ((this!=null)&&(esteBloque.getPrioridad()==1)){
					esteBloque.actuar(this);
				}
			}
			iterador =this.bloquesContiguos.iterator();
			while (iterador.hasNext()&&(!this.seMovio())){
				Bloque esteBloque=iterador.next();	
				if ((this!=null)&&(esteBloque.getPrioridad()==3)){
					esteBloque.actuar(this);
				}
			}
		}
	}
	
	public void acelerar(){
		// Aca se tiene que poder acelerar su velocidad
		// en ciertas unidades, por ahora dejo sumar a una
		// unidad
		if (this.velocidad==1)
			this.velocidad++;
	}
	
	public void morir(){
		// Aca se tiene que poder eliminarlo del planeta
		// en nuestro caso sera eliminado de la matriz
		this.estaMuerto=true;
	}
	
	public void salvar(){
		this.estaSalvado=true;
	}
	
	public boolean estaMuerto(){
		return this.estaMuerto;		
	}
	
	public boolean estaSalvado(){
		return this.estaSalvado;		
	}

	public Bloque getBloqueActual(){
		return this.bloqueActual;		
	}
	
	public Image getImagen() {		
		if (haciaDerecha())
			return this.imagenPooglinDerecha;
		else{
			return this.imagenPooglinIzquierda;
		}
	}
	
	public Element toXml(Document doc){
		Element xmlElement = doc.createElement("Pooglin");
		xmlElement.setAttribute("velocidad", ""+this.velocidad);
		xmlElement.setAttribute("bloquesCaidos", ""+this.bloquesCaidos);
		xmlElement.setAttribute("haciaDerecha", ""+this.haciaDerecha);
		xmlElement.appendChild(this.posicionEnPlaneta.toXml(doc));
		xmlElement.setAttribute("estaMuerto", ""+this.estaMuerto);
		xmlElement.setAttribute("estaSalvado", ""+this.estaSalvado);
		if (this.habilidad!=null){
			xmlElement.setAttribute("Habilidad", "1");
			xmlElement.appendChild(this.habilidad.toXml(doc));
		}else{
			xmlElement.setAttribute("Habilidad", "0");
		}
		
		return xmlElement;
	}
	
	public void setTerrenoActual(Terreno terrenoActual) {
		this.terrenoActual = terrenoActual;
	}

}
